package com.wxh.bomb.netty.myrpc;

import com.wxh.bomb.netty.myrpc.utils.ServiceScaner;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * RPC服务提供者
 * @author wxh
 */
public class RpcProvider {

    private static Map<String, Object> SERVICE = new ConcurrentHashMap<String, Object>();
    static {
        register();
    }

    /**
     * 注册服务，将service下的服务全部注册进来
     */
    private static void register() {
        List<Class> classes = ServiceScaner.scanService();
        for (Class clz : classes) {
            Class<?>[] interfaces  = clz.getInterfaces();
            Object instance;
            try {
                instance = clz.newInstance();
            } catch (Throwable t) {
                throw new RuntimeException(clz.getName() + "类加载失败", t.getCause());
            }
            for (Class interfaceClz : interfaces ) {
                SERVICE.put(interfaceClz.getName(), instance);
                System.out.println(interfaceClz.getName() + " 注册成功！");
            }
        }

    }

    /**
     * 启动服务端
     */
    private void startup() {
        try {
            ServerSocket server = new ServerSocket(8081);
            System.out.println("服务启动成功！");
            while (true) {
                Socket socket = server.accept();
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());

                // 读取客户端请求数据，包含接口名 方法名称 参数类型 参数值
                String finger = in.readUTF();
                String interfaceName = in.readUTF();
                String methodName = in.readUTF();
                Class[] paramTypes = (Class[]) in.readObject();
                Object[] agrs = (Object[]) in.readObject();

                System.out.println("服务端接收到信息，信息如下:\n" + finger + "|" + interfaceName + "." + methodName + "|" + args2String(agrs));

                Object instance = getClass(interfaceName);
                Method method = instance.getClass().getMethod(methodName, paramTypes);
                Object result = method.invoke(instance, agrs);

                ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                out.writeObject(result);
                out.flush();
                in.close();
                out.close();
            }
        } catch (Throwable t) {
            t.printStackTrace();
            throw new RuntimeException("服务组件异常", t.getCause());
        }
    }

    /**
     * 获取服务接口
     * @param interfaceName 接口名称
     * @return 接口实现类
     */
    private Object getClass(String interfaceName) {
        Object instance = SERVICE.get(interfaceName);
        if (instance == null) {
            throw new RuntimeException("服务异常，未找到服务：" + interfaceName);
        }
        return instance;
    }

    /**
     * 参数转换为字符串
     * @param args 参数
     * @return 字符串
     */
    private String args2String(Object[] args) {
        if (args == null) {
            return "";
        }
        StringBuilder arg = new StringBuilder();
        arg.append("[");
        for (Object obj : args) {
            arg.append(obj.toString()).append(",");
        }
        arg.replace(arg.length() - 1, arg.length() , "");
        arg.append("]");
        return arg.toString();
    }

    public static void main(String[] args) {
        new RpcProvider().startup();
    }
}
